package com.cxf.windex.biz;

import com.cxf.windex.base.biz.BaseBiz;
import com.cxf.windex.base.common.ServiceException;
import com.cxf.windex.base.constant.UserConstant;
import com.cxf.windex.base.msg.ObjectRestResponse;
import com.cxf.windex.base.util.CommonUtil;
import com.cxf.windex.base.util.MD5Util;
import com.cxf.windex.config.MyWxConfig;
import com.cxf.windex.entity.BOrders;
import com.cxf.windex.entity.BShop;
import com.cxf.windex.entity.JsUser;
import com.cxf.windex.entity.PayInfo;
import com.cxf.windex.enums.OperateEnum;
import com.cxf.windex.mapper.PayInfoMapper;
import com.cxf.windex.service.WxPayService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PathVariable;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @program: cxf-mf
 * @description: 支付信息表
 * @author: chenxf
 * @create: 2018-05-31 15:57
 **/
@Service
public class PayInfoBiz extends BaseBiz<PayInfoMapper, PayInfo> {
    @Autowired
    private BOrdersBiz ordersBiz;
    @Autowired
    private BShopBiz shopBiz;
    @Autowired
    private MoneyBiz moneyBiz;
    @Value("${weixin.appid}")
    private String appid;

    @Value("${weixin.appKey}")
    private String appKey;

    @Value("${weixin.mechid}")
    private String mechid;

    @Value("${weixin.fee}")
    private BigDecimal fee;

    @Value("${weixin.totalFee}")
    private BigDecimal totalFee;

    @Value("${weixin.notifyUrl}")
    private String notifyUrl;
    /**
     * 获取认证费
     * @return map fee实际支付费用 totalFee显示支付费用
     */
    public Map certFee(){
        Map<String, String> resultMap = new HashMap<String, String>(4);
        resultMap.put("fee", fee.divide(new BigDecimal("100")).toString());
        resultMap.put("totalFee",totalFee.divide(new BigDecimal("100")).toString());
        return resultMap;
    }

    /**
     * 生成订单信息
     * @param openid openid
     * @param fee     支付金额
     * @param type    支付类型
     * @param bindId  绑定订单ID
     * @param clientIp 客户IP
     */
    public Map getOrderInfo(String openid,  String fee,  String type,   String bindId,String clientIp){
        Map<String, String> resultMap = new HashMap<String, String>(4);
        BigDecimal payMoney=new BigDecimal(fee).multiply(BigDecimal.valueOf(100));
        //检验用户
        BShop shop = shopBiz.getInfo(openid);
        if (shop == null) {
            throw new ServiceException("用户不存在 ");
        }
        //检验金额
        if(type.equals(OperateEnum.WX_CERT.getKey())){
            //检验认证费
            if(payMoney.intValue()!=this.fee.intValue()){
                throw new ServiceException("认证费异常");
            }
            //检验是否已付费
            PayInfo payInfo=selectOne(PayInfo.builder().userid(openid).payCode(type).status(0).build());
            if(payInfo!=null){
                throw new ServiceException("认证费已支付");
            }
        }
        if(type.equals(OperateEnum.WX_ORDERS.getKey())){
            //检验订单金额
            BOrders orders=ordersBiz.selectById(bindId);
            if(orders==null){
                throw new ServiceException("订单不存在");
            }
            PayInfo payInfo=selectOne(PayInfo.builder().userid(openid).payCode(type).status(0).bindId(bindId).build());
            if(payInfo!=null){
                throw new ServiceException("订单已支付");
            }
//           TODO 订单总价判断 暂时忽略
//          if(payMoney.intValue()!=orders.getTotalPrice().multiply(BigDecimal.valueOf(100)).intValue()){
//                throw new ServiceException("订单总价异常");
//            }
        }

        String attach = shop.getId() + "," + OperateEnum.getIdType(type).getDesc();
        String out_trade_no = CommonUtil.getRandomOrderId(shop.getId().toString());
        MyWxConfig config = new MyWxConfig(appid, mechid, appKey);
        Map<String, String> result = WxPayService
                .dounifiedOrder(config, attach, out_trade_no, openid, payMoney.intValue()+"", clientIp,
                        notifyUrl);
        Long time = System.currentTimeMillis() / 1000;
        String timestamp = time.toString();
        String nonce_str = result.get("nonce_str");
        String prepay_id = result.get("prepay_id");
        if (StringUtils.isBlank(prepay_id)) {
            throw new ServiceException("生成订单信息失败");
        }
        savePayInfo(shop.getName(),out_trade_no,fee,OperateEnum.getIdType(type),openid,bindId,clientIp);
        resultMap.put("appId", appid);
        resultMap.put("timeStamp", timestamp);
        resultMap.put("nonceStr", nonce_str);
        resultMap.put("package", "prepay_id=" + prepay_id);
        resultMap.put("signType", "MD5");
        resultMap.put("paySign", MD5Util.getSign(resultMap, config));
        resultMap.put("payId", out_trade_no);
        return resultMap;
    }



    public String payResult(HttpServletRequest request){
        String resXml = "";
        try {
            MyWxConfig config = new MyWxConfig(appid, mechid, appKey);
            //
            InputStream is = request.getInputStream();
            //将InputStream转换成String
            BufferedReader reader = new BufferedReader(new InputStreamReader(is));
            StringBuilder sb = new StringBuilder();
            String line = null;
            try {
                while ((line = reader.readLine()) != null) {
                    sb.append(line + "\n");
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            resXml = sb.toString();
            if (StringUtils.isBlank(resXml)) {
                String result = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
                        + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
                return result;
            }
            Map<String, String> resultMap = WxPayService.payBackMap(resXml, config);
            //设置技师状态

            if (resultMap.get("return_code").equals("SUCCESS")) {
                String out_trade_no = resultMap.get("out_trade_no");

                if (out_trade_no == null || StringUtils.isBlank(out_trade_no)) {
                    payFail(out_trade_no);
                } else {
                    if (resultMap.get("total_fee") == null || StringUtils
                            .isBlank(resultMap.get("total_fee"))) {
                        payFail(out_trade_no);
                    }
                    paySuccess(out_trade_no);
                }
            }
            if (resultMap.get("return_code").equals("FAIL")) {
                payFail(resultMap.get("out_trade_no"));
            }
            return resultMap.get("xmlBack");
        } catch (Exception e) {
            String result = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
                    + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
            return result;
        }
    }

    /**
     * 设置支付失败
     * @param payId 支付ID
     */
    public void payFail(String payId){
        PayInfo payInfo=selectOne(PayInfo.builder().payId(payId).build());
        updateSelectiveById(PayInfo.builder().id(payInfo.getId()).status(2).notes("支付失败").build());
    }

    public void paySuccess(String payId){
        PayInfo payInfo=selectOne(PayInfo.builder().payId(payId).build());
        updateSelectiveById(PayInfo.builder().id(payInfo.getId()).status(1).notes("支付成功").build());

        //处理相关业务
        switch (payInfo.getPayCode()){
            case "s_wx_recharge":
                //充值操作
                moneyBiz.recharge(payInfo.getUserid(),payInfo.getPayMoney().toString(), UserConstant.SHOP_RANGE);
                break;
            case "s_wx_cert":
                //认证操作
                moneyBiz.cert(payInfo.getUserid(),payInfo.getPayMoney().toString(), UserConstant.SHOP_RANGE);
                break;
            case "s_wx_orders":
                //订单支付
                moneyBiz.orderPay(payInfo.getUserid(),payInfo.getPayMoney().toString(), 2,payInfo.getBindId(),"");
                break;
            default:break;
        }
    }

    /**
     * 保存支付信息
     * @param name             店铺名称
     * @param payId            订单ID
     * @param fee              订单费用
     * @param operateEnum      订单类型
     * @param openId            openid
     * @param bindId            绑定订单ID
     * @param clientIp          支付IP
     */
    private void savePayInfo(String name,String payId,String fee,OperateEnum operateEnum,String openId,String bindId,String clientIp){
        insertSelective(PayInfo.builder().name(name).payId(payId).addtime(new Date()).payMoney(new BigDecimal(fee)).totalMoney(new BigDecimal(fee))
                .payCode(operateEnum.getKey()).payName(operateEnum.getDesc()).userid(openId).bindId(bindId).clientIp(clientIp).status(0).build());

    }

}
